perm filename PLAYX.FAI[MUS,LCS] blob
sn#097599 filedate 1974-04-16 generic text, type T, neo UTF8
TITLE BUFFER; DOROTHY BENDER ****** GARPLY *******
; ROUTINE TO READ THE OUTPUT FROM THE MUSIC
; PROGRAM AND CALL THE D-A CONVERTER TO PLAY.
;
; THE NAME OF THE FILE TO BE INPUTTED IS 'MUSIC',
; THE FIRST RECORD OF WHICH CONTAINS THE
; NUMBER OF WORDS OF DATA IN THE ENTIRE DISK FILE.
EXTERNAL CORGET,FSINIT
A ← 1 ;WORK
B ← 2 ;WORK
P←17
BLOCK←4
SIZE←5
RET ← 3 ;RETURN ACCUMULATOR
PLN←20
PDL: BLOCK PLN
;;BUFSIZ ←=20224
↓DSKCHN ←1 ;DISK CHANNEL FOR INPUT
↓ADCHN ←2 ;D-A CHANNEL FOR OUTPUT
OPDEF READCH [51B8]
OPDEF MESSAGE[51B8!3B12]
BEG: CALLI 0,0 ;RESET I/O DEVICES
MOVE P,[IOWD PLN,PDL]
PUSHJ P,FSINIT
MOVEI SIZE1←=20224
PUSHJ P,CORGET
HALT,
SUBI BLOCK,1
MOVEM BLOCK, LOOP+1
PUSHJ P,CORGET
HALT,
SUBI BLOCK,1
MOVEM BLOCK, LOOP+4
OPEN DSKCHN,[17 ;MODE
'DSK ' ;DEVICE NAME
0] ;NO BUFFER HEADERS
HALT BEG ;RESTART IF DEVICE IS UNAVAILABLE
SETZM FILBLK+3 ;FOR RESTART
SETZM FILBL2+3 ;FOR RESTART
LX: MESSAGE [ASCIZ/
TYPE `P' TO PLAY FROM DISK, `C' TO COPY TAPE TO DISK.
/]
readch a
cain a,"C"
jrst start
caie a,"P"
jrst lx
skipe filblk+3 ;is this first time through ?
jrst pla2 ;No. Parameters already set up.
;FIND OUT NUMBER OF CHANNELS AND
;THE SPEED.
MESSAGE [ASCIZ/HOW MANY CHANNELS?/]
READCH A
SUBI A,"0"+1 ;CONVERT TO BINR AND ADD 1
DPB A,[POINT 2,OUTBIT,26]
MESSAGE [ASCIZ/WHAT IS THE SPEED?/]
READCH A
SUBI A,"0"
DPB A,[POINT 3,OUTBIT,32]
PLA2: SETZM FILBLK+3
SETZM FILBL2+3
LOOKUP DSKCHN,FILBLK
SKIPA ;CAN'T FIND MUSIC.MUS
JRST XOPEN ;FOUND IT
LOOKUP DSKCHN,FILBL2 ;TRY FOR MUSAA.DMD
JRST [MESSAGE[ASCIZ/
*** MUSIC FILE NOT FOUND/]
CALLI 12]
;EXIT IF FILE IS MISSING
MOVE A,FILBL2+3 ;GET LENGTH OF MUSAA.DMD
MOVEM A,FILBLK+3;PUT IT IN RIGHT PLACE
XOPEN: OPEN ADCHN,[117 ;MODE
'AD ' ;DEVICE NAME
0] ;NO BUFFER HEADERS
JRST [MESSAGE[ASCIZ/
***D-A NOT AVAILABLE/]
CALLI 12]
;EXIT IF D-A IS UNAVAILABLE
SPWAR: SPCWAR 17,[CALLI]
MESSAGE [ASCIZ/ GO? /]
READCH A
LNTH: movs a,filblk+3 ;get length of file.
movnm a,nwd
; -----------------------------------------
;BEGIN MAIN BODY OF PROGRAM
LOOP: JSP RET,SUB ;ROUTINE TO READ AND WRITE
;; BUF1-1 ;USE BUF1 FOR THE I/O
0
JUMPLE B,OUT ;DONE
JSP RET,SUB ;CALL IT AGAIN
;; BUF2-1 ;USE BUF2 FOR THE I/O
0
JUMPG B,LOOP ;GO BACK FOR MORE IF B>0
OUT: close dskchn, ;END OF PROGRAM.
releas adchn,
SPCWAR 0,'SSW'
jrst lx
;SUBROUTINE TO SET UP IOWD AND READ AND WRITE.
; 1(RET) WILL BE THE RETURN
; 0(RET) WILL BE THE ADDRESS OF THE BUFFER TO BE
; PUT IN THE RIGHT HALF OF THE IOWD.
; A WILL BE A WORK REGISTER
; B WILL BE TESTED ON THE OUTSIDE.
SUB: MOVNI A,BUFSIZ ;PICK UP AND COMPLEMENT BUFSIZ
ADDB A,NWD ;A←NWD-BUFSIZ
;NWD←NWD-BUFSIZ
MOVE B,A ;SAVE B TO BE TESTED FOR LAST
;TIME.
JUMPL A,LAST ;SET UP FOR LAST TIME.
MOVEI A,0
;THE IOWD LOOKS LIKE:
; [-BUFSIZ / BUFI-1]
LAST: ADDI A,BUFSIZ
MOVNS A ;COMPLEMENT A
HRL A,0(RET) ;PICK UP BUFI AND MOVE IT
;TO THE LEFT SIDE OF A.
MOVSM A,INLIST ;SWAP A AND MOVE IT.
MOVSM A,OUTWC ;SAME FOR OUTPUT.
INPUT DSKCHN,INLIST ;READ A RECORD.
OUTPUT ADCHN,OUTWC ;WRITE THE RECORD.
JRST 1(RET) ;RETURN
; -----------------------------------------
; STORAGE:
NWD: 0 ;FOR NUMBER OF WORDS OF INPUT.
;;↓BUF1: BLOCK BUFSIZ+1 ;BUFFER 1
;;BUF2: BLOCK BUFSIZ+1 ;BUFFER 2
FILBLK: 'MUSIC ' ;FILENAME FOR INPUT
'MUS ' ;EXTENSION
0 ;INFORMATION ON FILE
0 ;PROJECT PROG#
FILBL2: 'MUSAA ' ;FILENAME FOR INPUT, 2ND CHOICE
'DMD ' ;EXTENSION
0 ;INFORMATION ON FILE
0 ;PROJECT PROG#
CLIST: IOWD 1,NWD ;FOR THE FIRST RECORD
0
INLIST: 0 ;WILL CONTAIN AN IOWD
0
OUTWC: 0 ;WILL CONTAIN AN IOWD FOR D-A
3650 ;MAGIC BITS FOR 136.
OUTBIT: 4000 ;BITS FOR D-A
BLOCK 2
begin magdsk
A←1
B←2
D←3
OLNG←=2432 ;size of mag tape records. must be multiple of =128.
ILNG←=2432
ichn←adchn
ochn←dskchn
↑START: CALLI 0
INIT ICHN,3B28+17
SIXBIT /MTA0/
0
HALT
MTAPE ICHN,1 ;REWIND THE TAPE
JFCL
INIT OCHN,17
SIXBIT /DSK/
0
HALT
ENTER OCHN,[SIXBIT /MUSIC/
SIXBIT /MUS/
0
0]
HALT
loop:input ichn,olst
statz ichn,20000
jrst out ;end of tape.
output ochn,olst
jrst loop
OLST: IOWD OLNG,OBUF
0
obuf←← buf1
bend magdsk
end beg
ENTRY CORGET,CORREL,FSINIT
TITLE CORGET
INTERNAL FSINIT,CORGET,CORREL
EXTERNAL JOBREL,JOBSA,JOBFF,JOBDDT,JOBSYM
THIS←2
SIZ←3
NEXT←4
PREV←5
LAST←6
USER←7
TEMP←10
P←17
INTEGER TOP,FRELST,LOWC
TRIVIAL←←5
ARRAY BUFACS[20]
DEFINE TERPRI(A) <
PUSHJ P,[
OUTSTR [ASCIZ /A
/]
JRST 4,CPOPJ]
>
DEFINE ERR(A) <
OUTSTR [ASCIZ /A
/]
>
; UTILITY ROUTINES. SAVE AND GET ACCUMULATORS
FSINIT: MOVEI TEMP,-1 ;FOR MAX CORE
MOVEM TEMP,JOBFF ; IS DOING
HLRZ USER,JOBSA
SKIPN JOBDDT ;IF DDT IS IN CORE,
JRST NODDT ; MAKE SURE ITS SYMBOLS ARE PROTECTED
HRRZ TEMP,JOBSYM ;IF JOBSYM IS BELOW JOBFF, THEN
CAML TEMP,USER ; ASSUME ALL SYMBOLS ARE BELOW.
TERPRI <YOUR SYMBOLS ARE SOON TO BE OBLITERATED>
NODDT: SETZM FRELST ; CLEAR POINTERS
SETZM TOP
MOVEI THIS,(USER)
MOVEM THIS,LOWC ; SET BOTTOM OF CORE
PUSHJ P,NEWBLK ;MAKE NEW AREA INTO A FREE BLOCK
JRST JUSTSAVE ;SAVE ACS
NEWBLK:
HRRZ LAST,JOBREL ;END OF BIG BLOCK
NEWB1: SETZM (THIS) ;POINTERS WORD IN BIG BLOCK
ADDI LAST,1 ;CONFORM TO "LAST" STANDARDS
MOVEM LAST,TOP ;TOP OF FREE SPACE
PUSH P,SIZ ;SAVE SIZE
MOVE SIZ,LAST ;COMPUTE SIZE OF NEW BLOCK
SUB SIZ,THIS ;SIZE OF BIG BLOCK
PUSHJ P,RELINK ;PUT ON FREE STORAGE LIST
POP P,SIZ ;GET SIZ BACK
CPOPJ: POPJ P,
JUSTSAVE:
MOVEM TEMP,BUFACS+TEMP
MOVEI TEMP,BUFACS
BLT TEMP,BUFACS+LAST
POPJ P,
BUFRST: MOVSI TEMP,BUFACS
BLT TEMP,TEMP
POPJ P,
; ROUTINES TO LINK AND UNLINK A BLOCK INTO THE FREE LIST
; CALL WITH ADDRESS IN THIS AND SIZE IN SIZ
UNLINK:
HRRZ NEXT,(THIS) ;→NEXT BLOCK
HLRZ PREV,(THIS) ;→PREVIOUS BLOCK
SKIPN PREV ;IF A PREV BLOCK DOES NOT EXIST,
MOVEI PREV,FRELST ; USE FRELST POINTER
HRRM NEXT,(PREV) ;CHANGE ITS NEXT FIELD
SKIPE NEXT ;IF A NEXT BLOCK EXISTS,
HRLM PREV,(NEXT) ; CHANGE ITS PREV FIELD
POPJ P, ;BLOCK IN "THIS" IS NO LONGER ON FRELST
RELINK:
HRRZM THIS,-1(LAST) ;X-BIT ← 0, RH ← PTR TO HEAD
MOVEM SIZ,1(THIS) ;GREATER 0 SIZE FIELD ⊃ FREE BLOCK
SKIPE NEXT,FRELST ;PLACE NEW BLOCK ON FRONT OF FRELST
HRLM THIS,(NEXT) ; IF THERE IS ONE
HRRZM NEXT,(THIS) ;POINT TO NEXT FROM THIS
HRRZM THIS,FRELST ;UPDATE FRELST POINTER
POPJ P, ;RETURN
; ROUTINE TO GET CORE
; CALL WITH SIZE IN AC 3
; RETURNS BLOCK IN 2
; SAVES ALL ACCUMULATORS
CORGET:
PUSHJ P,JUSTSAV ;SAVE AC'S, INITIALIZE WORLD PERHAPS
COR21: ADDI SIZ,3 ;3 WORDS FOR CONTROL INFO
MOVEI THIS,FRELST ;THIS WILL POINT TO THE FIRST GOOD BLOCK
GETLUP: HRRZ THIS,(THIS) ;→NEXT FREE BLOCK
JUMPE THIS,EXPAND ;TRY TO EXPAND CORE, NONE EXIST YET
CAMLE SIZ,1(THIS) ;WILL IT FIT?
JRST GETLUP ; NO, TRY NEXT
GETCOR: AOS (P) ;SUCCESS GUARANTEED
HRRZM THIS,BUFACS+THIS ;RESULT(ALMOST)
PUSHJ P,UNLINK ;UNLINK THIS BLOCK
MOVE LAST,1(THIS) ;REAL BLOCK SIZE
CAIGE LAST,TRIVIAL(SIZ) ;IS DIFFERENCE NEGLIGIBLE?
JRST [MOVSI TEMP,400000 ;YES, USE WHOLE THING --
ADD LAST,THIS ; MARK X-BIT TO INDICATE IN USE
HLLM TEMP,-1(LAST)
JRST GETOUT] ;AND GO FINISH OUT
MOVEM SIZ,1(THIS) ;NEW SIZE FOR RESULT
HRRZ TEMP,THIS ;SAVE START OF BLOCK (RESULT)
ADD THIS,SIZ ;NEW START FOR REMAINING FREE STUFF
SUB LAST,SIZ ;NEW SIZE FOR REMAINS
MOVE SIZ,LAST
ADD LAST,THIS ;NEW END FOR REMAINS
HRLI TEMP,400000 ;TURN X-BIT ON
MOVEM TEMP,-1(THIS) ;IN USER'S BRAND NEW BLOCK
PUSHJ P,RELINK ;RELINK REMAINS, RESTORE ACS
GETOUT: PUSHJ P,BUFRST ;RESTORE ACS
SETZM (THIS) ;PTR RETRIEVED FROM STORAGE
MOVNS 1(THIS) ;SIZE NEG ⊃ IN USE
ADDI THIS,2 ;USER DOESN'T SEE THIS HEADER
POPJ P, ;HERE'S YOUR BLOCK!
; HERE WE INCREASE THE JOB CORE SIZE
EXPAND: PUSH P,SIZ ;SAVE TOTAL SIZE
HRRZ THIS,TOP ;THIS→NEW BLOCK IF NEXT LOWER IS USED
SKIPGE -1(THIS) ;IS TOP BLOCK FREE?
JRST GETMOR ; NO, USE WHAT YOU HAVE
HRRZ THIS,-1(THIS) ;UNLINK THE
PUSHJ P,UNLINK ; TOP BLOCK
GETMOR: MOVE TEMP,THIS
ADDI TEMP,=1024(SIZ) ;GET MORE AND THEN SOME
POP P,SIZ ;GET THIS BACK BEFORE YOU FORGET
CALL TEMP,[SIXBIT /CORE/] ;ASK FOR MORE
JRST BUFRST ;CAN'T GET IT
PUSHJ P,NEWBLK ;MAKE TOP LOOK LIKE FREE BLOCK
CAMLE SIZ,1(THIS) ;NOW SHOULD FIT
ERR <DRYROT -- EXPAND CODE GLUBBED UP>
JRST GETCOR
; ROUTINE TO RELEASE CORE, ENTER WITH BLOCK ADDRESS IN 2
CORREL:
PUSHJ P,JUSTSAVE ;SAVE ACS
; MERGE WITH LOWER NEIGHBOR (ADDRESS-WISE) IF POSSIBLE
SUBI THIS,2 ;USER THINKS IT STARTED 2 PAST
MOVN SIZ,1(THIS) ;SIZE OF THIS BLOCK
MOVE LAST,SIZ ;ADDRESS OF UPPER
ADD LAST,THIS ; NEIGHBOR
CAMGE THIS,LOWC ;IS ADDRESS IN RANGE?
ERR <DRYROT -- BAD ADDRESS TO BUFREL>
CAME THIS,LOWC ;CAN THERE BE A LOWER BLOCK
SKIPGE -1(THIS) ; AND IF SO, IS IT FREE?
JRST UPPET ; NO, LOOK FOR UPPER BLOCK
HRRZ THIS,-1(THIS) ;→LOWER BLOCK
PUSHJ P,UNLINK ;UNLINK IT FROM LIST
ADD SIZ,1(THIS) ;INCREASE SIZE
; MERGE WITH UPPER NEIGHBOR IF POSSIBLE
UPPET: CAMLE LAST,TOP
ERR <YOU ARE ABOUT TO GET AN ILL MEM-REF>
CAME LAST,TOP ;IS THERE AN UPPER BLOCK?
SKIPGE 1(LAST) ;AND IF SO, IS IT FREE?
JRST LNKRET ; NO, RELINK AND GO AWAY
UPPR: PUSH P,THIS
HRRZ THIS,LAST ;THIS → UPPER NEIGHBOR
PUSHJ P,UNLINK ;GET IT OUT
ADD LAST,1(THIS) ; INCREASE EXTENT
ADD SIZ,1(THIS) ; AND TOTAL SIZE
POP P,THIS ; GET HEADER POINTER BACK
; HERE WE TRY TO SHRINK CORE
LNKRET:
CAMG LAST,JOBREL ;THIS IS THE LAST CORE BLOCK, AND
JRST LNKRT
CAIGE SIZ,=2046 ; IT IS MORE THAN 2K LONG,
JRST LNKRT
MOVEI TEMP,=2046(THIS) ;THEN 1) SHRINK CORE TO 2K FOR LAST BLOCK
CALL TEMP,[SIXBIT /CORE/]
ERR <DRYROT --CORSER&LNKRET>
MOVE LAST,JOBREL ; AND 2) ADJUST BLOCK TO INDICATE
ADDI LAST,1
MOVEM LAST,TOP ;AND RECORD NEW RESULTS.
MOVE SIZ,LAST ;THE CHANGE BEFORE RELINKING
SUB SIZ,THIS
LNKRT:
PUSHJ P,RELINK ;PUT IT BACK
JRST BUFRST ;AND GO AWAY
END